package com.ryan.ohos.extension;

import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.utils.Rect;

import java.util.HashMap;

/**
 * 滚动component内容的帮助类，由于{@link Component}内的{@link Component#scrollTo(int, int)}、{@link Component#scrollBy(int, int)}
 * 等api在普通控件内无效，因此通过{@link Component#setComponentPosition(Rect)}来模拟实现该api
 *
 * 注意：此api只负责滚动内容，滚动边界需要自己计算
 */
public class ScrollApiHelper {
    private final HashMap<Integer, Rect> positions = new HashMap<>();
    private final Rect temp = new Rect();

    private final ComponentContainer container;

    private int scrollX;
    private int scrollY;

    private int offsetToScrollX;
    private int offsetToScrollY;

    private int scrollRangeX = Integer.MAX_VALUE;
    private int scrollRangeY = Integer.MAX_VALUE;

    public ScrollApiHelper(ComponentContainer container) {
        this.container = container;
    }

    public void resetAll() {
        resetSavedPositions();
        scrollX = 0;
        scrollY = 0;
        offsetToScrollX = 0;
        offsetToScrollY = 0;
        scrollRangeX = Integer.MAX_VALUE;
        scrollRangeY = Integer.MAX_VALUE;
    }

    public void resetSavedPositions() {
        positions.clear();
    }

    public void setScrollRangeX(int scrollRangeX) {
        this.scrollRangeX = scrollRangeX;
    }

    public void setScrollRangeY(int scrollRangeY) {
        this.scrollRangeY = scrollRangeY;
    }

    /**
     * 设置x轴滚动的偏移量
     * @param offsetToScrollX 偏移量
     */
    public void setOffsetToScrollX(int offsetToScrollX) {
        this.offsetToScrollX = offsetToScrollX;
    }

    /**
     * 设置y轴滚动的偏移量
     * @param offsetToScrollY 偏移量
     */
    public void setOffsetToScrollY(int offsetToScrollY) {
        this.offsetToScrollY = offsetToScrollY;
    }

    public int getScrollX() {
        return scrollX;
    }

    public int getScrollY() {
        return scrollY;
    }

    public void scrollTo(int x, int y) {
        scrollX = x;
        scrollY = y;

        if (scrollX < 0) {
            scrollX = 0;
        }

        if (scrollY < 0) {
            scrollY = 0;
        }

        if (scrollX > scrollRangeX) {
            scrollX = scrollRangeX;
        }

        if (scrollY > scrollRangeY) {
            scrollY = scrollRangeY;
        }

        int count = container.getChildCount();
        for (int i = 0; i < count; i++) {
            Component child = container.getComponentAt(i);
            Rect rect = positions.get(child.hashCode());
            if (rect == null) {
                rect = child.getComponentPosition();
                positions.put(child.hashCode(), rect);

                if (rect != null) {
                    offsetPosition(child, rect, scrollX, scrollY);
                }
            } else {
                offsetPosition(child, rect, scrollX, scrollY);
            }
        }
    }

    public void scrollBy(int deltaX, int deltaY) {
        scrollTo(scrollX + deltaX, scrollY + deltaY);
    }

    private void offsetPosition(Component child, Rect rect, int scrollX, int scrollY) {
        temp.left = rect.left - scrollX + offsetToScrollX;
        temp.right = rect.right - scrollX + offsetToScrollX;
        temp.top = rect.top - scrollY + offsetToScrollY;
        temp.bottom = rect.bottom - scrollY + offsetToScrollY;

        child.setComponentPosition(temp);
    }
}
